/*
 * @author hzq
 * @status done
 * @see 🚀 https://juejin.cn/post/7452667228006678540
 * @date 2024-12-31 16:44:49
 * @description 一个vue3指令让el-table自动轮播
 * @usage 需要在Element plus中el-table组件上使用v-tableAutoScroll指令，并传入一个对象，包含delay属性，表示滚动间隔时间，单位为毫秒，默认为15毫秒
 */

import type { Directive, DirectiveBinding } from 'vue'

interface ElType extends HTMLElement {
  timer: number | null
  isScroll: boolean
  curTableTopValue: number
}

/**
 * 表格自动滚动指令
 */
export const tableAutoScroll: Directive = {
  // 在指令创建时执行
  created(el: ElType) {
    // 将timer属性初始化为null
    ;(el.timer = null), (el.isScroll = true), (el.curTableTopValue = 0)
  },
  // 在指令绑定到元素上时执行
  mounted(el: ElType, binding: DirectiveBinding) {
    // 获取指令的值，默认延迟为15
    const { delay = 15 } = binding.value || {}
    // 获取表格的DOM元素
    const tableDom = el.getElementsByClassName(
      'el-scrollbar__wrap'
    )[0] as HTMLElement
    // 获取表格视图的DOM元素
    const viewDom = el.getElementsByClassName(
      'el-scrollbar__view'
    )[0] as HTMLElement

    // 鼠标悬停时停止滚动
    const onMouseOver = () => {
      el.isScroll = false
    }
    // 鼠标移出时继续滚动
    const onMouseOut = () => {
      el.curTableTopValue = tableDom.scrollTop
      el.isScroll = true
    }
    // 添加鼠标悬停和移出事件监听
    tableDom.addEventListener('mouseover', onMouseOver)
    tableDom.addEventListener('mouseout', onMouseOut)

    // 设置定时器，每隔delay毫秒执行一次
    el.timer = window.setInterval(() => {
      // 获取表格视图的高度
      const viewDomClientHeight = viewDom.clientHeight
      // 获取表格的高度
      const tableDomScrollTop = el.clientHeight
      // 如果表格正在滚动且表格视图的高度大于表格的高度
      if (el.isScroll && viewDomClientHeight > tableDomScrollTop) {
        // 获取当前滚动位置
        const curScrollPosition = tableDom.clientHeight + el.curTableTopValue
        // 如果滚动位置等于表格的总高度，则将滚动位置重置为0
        el.curTableTopValue =
          curScrollPosition === tableDom.scrollHeight
            ? 0
            : el.curTableTopValue + 1
        // 设置表格的滚动位置
        tableDom.scrollTop = el.curTableTopValue
      }
    }, delay)
  },
  // 在指令与元素解绑时执行
  unmounted(el: ElType) {
    // 清除定时器
    el.timer && clearInterval(el.timer)
    el.timer = null
    // 获取表格的DOM元素
    const tableDom = el.getElementsByClassName(
      'el-scrollbar__wrap'
    )[0] as HTMLElement
    // 移除鼠标悬停和移出事件监听
    tableDom.removeEventListener('mouseover', () => (el.isScroll = false))
    tableDom.removeEventListener('mouseout', () => {
      el.curTableTopValue = tableDom.scrollTop
      el.isScroll = true
    })
  }
}
